#include #include #include #include #include #include using namespace std; #define FOR(i, a, b) for (int i = (a); i <= (b); i++) #define FORN(i, a, b) for (int i = (a); i < (b); i++) #define REP(i, n) for (int i = 0; i < (n); i++) #define FORD(i, a, b) for (int i = (a); i >= (b); i--) #define BUG(x) cerr << #x << " = " << x << endl #define SIZE(a) ((int) a.size()) typedef pair pii; #define MAXN 112345 struct Cycle { int order; //larger order mean the cycle is closer to the root int top; int length; }; struct Neighbor { int node; int edgeIndex; int cost; Neighbor(int node, int edgeIndex, int cost): node(node), edgeIndex(edgeIndex), cost(cost) { } }; Cycle cycle[MAXN]; int parent[MAXN], distanceToParent[MAXN]; int distanceToTop[MAXN], nodeToCycleIndex[MAXN]; int d[MAXN], depth[MAXN]; int f[MAXN][20], maxOrder[MAXN][20]; bool visited[MAXN]; vector neighbors[MAXN]; bool usedEdge[2 * MAXN]; int n, m, cycleCnt, _cycleOrder; //build the dfs tree and prepare some infomation void dfs(int u) { REP(i, SIZE(neighbors[u])) { Neighbor nb = neighbors[u][i]; int v = nb.node; int edgeIndex = nb.edgeIndex; int c = nb.cost; //never go to an used edge if (usedEdge[edgeIndex]) { continue; } usedEdge[edgeIndex] = true; if (!parent[v]) { distanceToParent[v] = c; parent[v] = u; dfs(v); } else { //we got a cycle cycleCnt++; cycle[cycleCnt].top = v; cycle[cycleCnt].length = c; int x = u; distanceToTop[u] = c; while (true) { nodeToCycleIndex[x] = cycleCnt; if (x == v) { break; } cycle[cycleCnt].length += distanceToParent[x]; distanceToTop[parent[x]] = distanceToTop[x] + distanceToParent[x]; x = parent[x]; } } } int index = nodeToCycleIndex[u]; //if the dfs of cycle index is complete we give it its order if (index && cycle[index].top == u) { _cycleOrder++; cycle[index].order = _cycleOrder; } } int getCycleOrder(int u) { int index = nodeToCycleIndex[u]; if (!index) { return 0; } return cycle[index].order; } int disSameCycle(int u, int v) { assert(nodeToCycleIndex[u] == nodeToCycleIndex[v]); int index = nodeToCycleIndex[u]; int dis = abs(distanceToTop[u] - distanceToTop[v]); return min(dis, cycle[index].length - dis); } //prepare d[], lca and maxOrder information void dfs2(int u) { visited[u] = true; //LCA prep f[u][0] = parent[u]; maxOrder[u][0] = max(getCycleOrder(u), getCycleOrder(parent[u])); FOR (i, 1, 17) { f[u][i] = f[f[u][i - 1]][i - 1]; maxOrder[u][i] = max(maxOrder[u][i - 1], maxOrder[f[u][i - 1]][i - 1]); } REP(i, SIZE(neighbors[u])) { Neighbor nb = neighbors[u][i]; int v = nb.node; int edgeIndex = nb.edgeIndex; int c = nb.cost; if (!visited[v]) { int index = nodeToCycleIndex[v]; if (!index || cycle[index].top == v) { d[v] = d[u] + c; } else { int top = cycle[index].top; d[v] = d[top] + disSameCycle(v, top); } depth[v] = depth[u] + 1; dfs2(v); } } } int lca(int u, int v) { if (depth[u] > depth[v]) { swap(u, v); } FORD(i, 17, 0) { if (depth[f[v][i]] >= depth[u]) { v = f[v][i]; } } if (u == v) { return u; } FORD(i, 17, 0) { if (f[u][i] != f[v][i]) { u = f[u][i]; v = f[v][i]; } } return parent[u]; } //distance from an ancestor to one of its descendent int disTopDown(int ancestor, int u) { int index = nodeToCycleIndex[ancestor]; //if ancestor does not belong to any cycle if (!index) { return d[u] - d[ancestor]; } //if two vertices is in the same cycle if (index == nodeToCycleIndex[u]) { return disSameCycle(ancestor, u); } //we find b as the vertex in cycle index that is closest to u int b = u; FORD(i, 17, 0) { if (maxOrder[b][i] < cycle[index].order) { b = f[b][i]; } } b = parent[b]; return d[u] - d[b] + disSameCycle(ancestor, b); } int calc(int u, int v) { int r = lca(u, v); return disTopDown(r, u) + disTopDown(r, v); } int main() { cin >> n >> m; REP(i, m) { int u, v, c; cin >> u >> v >> c; neighbors[u].push_back( Neighbor(v, i, c) ); neighbors[v].push_back( Neighbor(u, i, c) ); } //first DFS parent[1] = 1; dfs(1); //second DFS dfs2(1); int q; cin >> q; while (q--) { int u, v; cin >> u >> v; cout << calc(u, v) << endl; } return 0; }